﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using eTerm.NetSocket;
using System.IO;
using System.Threading;
using System.Text.RegularExpressions;
using System.Net.Mail;
using System.Security.Cryptography;
using System.Web.Security;

namespace eTerm.PlugIn.NCore
{
    /// <summary>
    /// eTerm连接插件基类
    /// </summary>
    public abstract class BaseSocketPlugIn:BasePlugIn
    {
        private eTermSocketSetup __socketSetup = null;
        private BaseTermSocket __Socket;
        private string __KeyFileName = string.Empty;
        private string NoticeName = string.Empty;
        private string SystemCode = string.Empty;
        private LicenceManager __KeyManager = new LicenceManager();

        private string MailXslt = string.Empty;
        MailHelper helper = new MailHelper();
        string DebugMail = string.Empty;
        MailServerInfo server = new MailServerInfo();

        /// <summary>
        /// 初始化eTerm配置连接信息.
        /// </summary>
        protected virtual void InitSocketSetup()
        {
            if (XmlRoot == null) return;
            __socketSetup = SetEntity<eTermSocketSetup>(@"SocketSetup");
            __KeyFileName =Path.Combine(AssemblyPath, GetElementValue(@"KeyFileName"));
        }


        /// <summary>
        /// 插件授权码.
        /// </summary>
        /// <value>The plug in code.</value>
        protected abstract int PlugInCode { get; }


        /// <summary>
        /// 初始化自定义配置项
        /// </summary>
        protected override void SetCustomSetup()
        {
            InitSocketSetup();
            MailXslt =Path.Combine(AssemblyPath, GetElementValue(@"MailXslt"));
            NoticeName = GetElementValue(@"NoticeName");
            server = SetEntity<MailServerInfo>(@"MailServerInfo");
            helper = new MailHelper();
            helper.SmtpServer = server;
            helper.DEBUGReceiver = DebugMail;
            helper.OnException += (o, e) =>
            {
                FireOnNotify(e.BusinessNo, e.NotifyType, e.Notify);
            };
            helper.OnSent += (o, e) =>
            {
                FireOnNotify(e.BusinessNo, e.NotifyType, e.Notify);
            };
        }


        /// <summary>
        ///  MD5解密
        /// </summary>
        protected string MD5Decrypt(string Text)
        {
            return FormsAuthentication.HashPasswordForStoringInConfigFile(Text, "MD5");
        }



        /// <summary>
        /// 会话序号.
        /// </summary>
        /// <value>The get session id.</value>
        protected virtual string GetSessionId {
            get {
                return MD5Decrypt(__Socket.SessionId.ToString());
            }
        }


        /// <summary>
        /// 连接认证成功，开始指令序列.
        /// </summary>
        protected abstract void StartQueue();

        /// <summary>
        /// 指令结果分析.
        /// </summary>
        /// <param name="PakcetName">指令名称.</param>
        /// <param name="PakcetResult">指令结果.</param>
        protected abstract void ExecutePacket(string PakcetName, string PakcetResult);

        /// <summary>
        /// 设置授权文件并开启连接.
        /// </summary>
        protected virtual void Connect() {
            Connect(__KeyFileName);
        }


        /// <summary>
        /// 发送邮件.
        /// </summary>
        public void SendEmail( string Xml, MailAddressCollection to, MailAddressCollection cc, MailAddressCollection bcc){
            helper.SendEmail(MailXslt, Xml, to, cc,bcc, NoticeName);
        }


        /// <summary>
        /// 设置授权文件并开启连接.
        /// </summary>
        /// <param name="fileName">授权文件.</param>
        protected void Connect(string  fileName) {
            if (__socketSetup.IsSSL)
            {
                __Socket = new eTerm443Socket(__socketSetup.Server, __socketSetup.Port, __socketSetup.UserName, __socketSetup.Password, (byte)__socketSetup.RID, (byte)__socketSetup.SID);
            } else {
                __Socket = new eTerm350Socket(__socketSetup.Server, __socketSetup.Port, __socketSetup.UserName, __socketSetup.Password, (byte)__socketSetup.RID, (byte)__socketSetup.SID);
            }
            __Socket.SiText = __socketSetup.SiText;
            __Socket.SurplusCmdCount = UInt16.MaxValue;
            __Socket.AllowReconnect = false;
            __Socket.OnConnected += (o, e) =>
            {
                FireOnNotify(__socketSetup.UserName, EventType.INFO, string.Format(@"配置已连接 {0}", __socketSetup.Server));
            };
            __Socket.OnDisconnected += (o, e) =>
            {
                FireOnNotify(__socketSetup.UserName, EventType.WARNING, string.Format(@"配置已断开 {0}", __socketSetup.Server));
            };
            __Socket.OnDisconnecting += (o, e) =>
            {
                FireOnNotify(__socketSetup.UserName, EventType.WARNING, string.Format(@"配置即将断开 {0}", __socketSetup.Server));
                FireOnExecuted();
            };
            __Socket.OnKickedOff += (o, e) =>
            {
                FireOnNotify(__socketSetup.UserName, EventType.WARNING, string.Format(@"配置被强制踢出 {0}", __socketSetup.Server));
            };
            __Socket.OnReadPacket += (o, e) =>
            {
                try
                {
                    BaseTermSocket eTermSession = (o as BaseTermSocket);
                    byte[] buffer = eTermSession.Outpacket.GetStream();
                    if (buffer[8] == eTermSession.RID && buffer[9] == eTermSession.SID)
                    {
                        string cmd = Encoding.GetEncoding(@"gb2312").GetString(eTermSession.Depacket(buffer)).Trim();
                        string result = Encoding.GetEncoding(@"gb2312").GetString(eTermSession.Depacket(eTermSession.Inpacket.GetStream(), 5)).Trim();
                        result = result.Replace((char)0x0e, ' ');
                        if (eTermSession.ReceiveCount == 5)// Regex.IsMatch(cmd, @"^(IG)", RegexOptions.IgnoreCase | RegexOptions.Multiline))
                        {
                            StartQueue();
                            return;
                        }
                        FireOnNotify(cmd, EventType.INFO, "\r"+result);
                        ExecutePacket(cmd, result);
                    }
                }
                catch (Exception ex)
                {
                    FireOnNotify(__socketSetup.UserName, EventType.ERROR, string.Format(@"
    SOCKET读取异常：{0}
    异常跟踪信息：{1}", ex.Message, ex.StackTrace));
                    FireOnExecuted();
                }


            };
            __Socket.OnReceiveException += (o, e) =>
            {
                FireOnNotify(__socketSetup.UserName, EventType.ERROR, string.Format(@"配置读取异常：
    {0}", e.ExceptionMessage));
            };
            __Socket.OnSslAuthenticated += (o, e) =>
            {
                FireOnNotify(__socketSetup.UserName, EventType.INFO, string.Format(@"配置SSL认证完毕 {0}", __socketSetup.Server));
            };
            __Socket.OnValidated += (o, e) =>
            {
                FireOnNotify(__socketSetup.UserName, EventType.INFO, string.Format(@"配置登录认证完毕 {0}", __socketSetup.Server));
                //StartQueue();
            };
            __Socket.OnWritePacket += (o, e) =>
            {
                BaseTermSocket eTermSession = (o as BaseTermSocket);
                if (eTermSession.IsValidated)
                {
                    byte[] buffer = eTermSession.Outpacket.GetStream();
                    string Cmd = Encoding.GetEncoding(@"gb2312").GetString(eTermSession.Depacket(buffer)).Trim();
                    AfterSentPacket(Cmd);
                    FireOnNotify(eTermSession.UserName, EventType.INFO, string.Format(@"指令 {0} 发送完成", Cmd));
                }
            };
            using (FileStream fs = new FileStream(__KeyFileName, FileMode.Open))
            {
                byte[] buffer = new byte[fs.Length];
                BinaryReader br = new BinaryReader(fs);
                br.Read(buffer, 0, buffer.Length);
                __KeyManager.LicenceKeyBody = buffer;
            }
            __KeyManager.BeginValidate();
        }


        /// <summary>
        /// 指令发送后回调函数.
        /// </summary>
        /// <param name="PacketName">Name of the packet.</param>
        protected virtual void AfterSentPacket(string PacketName) { 
            
        }


        /// <summary>
        /// 结束插件调用事件通知.
        /// </summary>
        protected override void FireOnExecuted()
        {
            base.FireOnExecuted();
            __Socket.Dispose();
        }



        /// <summary>
        /// 指令发送.
        /// </summary>
        /// <param name="Cmd">指令.</param>
        protected void SendStream(string Cmd)
        {
            Thread.Sleep(1000);
            __Socket.SendStream(Cmd);
        }


        /// <summary>
        /// Handles the OnCompleted event of the LicenceManager control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="LicenceEventArgs"/> instance containing the event data.</param>
        private void LicenceManager_OnCompleted(object sender, LicenceEventArgs e) {
            SystemCode = e.SystemCode;
            FireOnNotify(e.SystemCode, EventType.SUCCESS, @"插件授权成功");
            try
            {
                __Socket.Connect(__KeyManager);
            }
            catch (Exception ex)
            {
                FireOnException(ex);
            }
        }

        /// <summary>
        /// Handles the OnFailed event of the LicenceManager control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="LicenceEventArgs"/> instance containing the event data.</param>
        private void LicenceManager_OnFailed(object sender, LicenceEventArgs e) {
            SystemCode = e.SystemCode;
            FireOnNotify(e.SystemCode, EventType.ERROR, @"插件授权失败");
            FireOnExecuted();
        }

        /// <summary>
        /// 绑定授权事件通知.
        /// </summary>
        protected void SetLicenceManagerEvent() {
            __KeyManager = new LicenceManager();
            __KeyManager.OnCompleted += LicenceManager_OnCompleted;
            __KeyManager.OnFailed += LicenceManager_OnFailed;
            __KeyManager.TargetType = PlugInCode;
        }


        /// <summary>
        /// 插件内部方法.
        /// </summary>
        protected override void ExecutePlugIn()
        {
            SetLicenceManagerEvent();
            Connect();
        }

        /// <summary>
        /// 完成插件后调用方法.
        /// </summary>
        protected override void AfterExecutePlugIn()
        {
            //base.AfterExecutePlugIn();
        }

        /// <summary>
        /// 释放插件资源
        /// </summary>
        protected override void DisposePlugIn()
        {
            base.DisposePlugIn();
            if (__Socket != null)
            {
                __Socket.Close();
                __Socket.Dispose();
                __Socket = null;
            }
        }


        #region 辅助方法
        /// <summary>
        /// 获取日期字符串辅助方法.
        /// </summary>
        /// <param name="date">The date.</param>
        /// <returns></returns>
        protected string getDateString(DateTime date)
        {
            MatchCollection regx = new Regex(@"[A-Z]{3,3}").Matches(date.ToString("R").ToUpper());

            //segment.DepartureDate.Value.Day.ToString("D2"), getDateString(segment.DepartureDate.Value))
            string r =  string.Format(@"{0}{1}", regx[1].Value, date.ToString("yy"));
            return string.Format(@"{0}{1}", date.Day.ToString("D2"), r);
        }

        #endregion

    }
}
